home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / HENSA / MATHS / PLPLOT / PLPLOT.ZIP / src / pldtik.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-30  |  4.8 KB  |  175 lines

  1. /* $Id: pldtik.c,v 1.7 1994/06/30 18:22:06 mjl Exp $
  2.  * $Log: pldtik.c,v $
  3.  * Revision 1.7  1994/06/30  18:22:06  mjl
  4.  * All core source files: made another pass to eliminate warnings when using
  5.  * gcc -Wall.  Lots of cleaning up: got rid of includes of math.h or string.h
  6.  * (now included by plplot.h), and other minor changes.  Now each file has
  7.  * global access to the plstream pointer via extern; many accessor functions
  8.  * eliminated as a result.
  9.  *
  10. */
  11.  
  12. /*    pldtik.c
  13.  
  14.     Determines tick spacing and mode (fixed or floating) of
  15.     numeric axis labels.
  16. */
  17.  
  18. #include "plplotP.h"
  19.  
  20. #define MIN_FLTDIG    3    /* disregarded if fractional part is 0 */
  21. #define MAX_FIXDIG_POS    6
  22. #define MAX_FIXDIG_NEG    4
  23. #define DIGMAX_DEF    5
  24.  
  25. /*----------------------------------------------------------------------*\
  26.  * void pldtik()
  27.  *
  28.  * If tick == 0, this works out a "nice" interval, so that there are
  29.  * between 3 and 7.5 major tick intervals in the input range "vmin" to
  30.  * "vmax". Using this value for the tick interval or supplied value, it
  31.  * also computes "prec" which specifies the number of places that should
  32.  * be written after the decimal point. The recommended number of subticks
  33.  * is returned in "nsubt" unless the routine is entered with a non-zero
  34.  * value of "nsubt".  The output variable "mode" is set to 0 if labels are
  35.  * to be written in floating-point format, or to 1 if they are to be
  36.  * written in scientific format.  For mode = 1, the exponent will be
  37.  * placed at:
  38.  *
  39.  *     top left    for vertical axis on left
  40.  *     top right    for vertical axis on right
  41.  *     bottom right    for horizontal axis
  42.  *
  43.  * The digmax flag can be set by the user, and represents the maximum
  44.  * number of digits a label may occupy.  If digmax<0, it is disregarded,
  45.  * and if digmax=0 the default value is used.  For digmax>0, mode=1 is
  46.  * chosen if there is insufficient room for the label within the specified
  47.  * # of digits.
  48.  *
  49.  * In the case of mode=0, the actual # of digits will become too large
  50.  * when the magnitude of the labels become too large.  The mode=1 case
  51.  * offers the greatest precision for the smallest field length.
  52.  *
  53.  * The determination of maximum length for fixed point quantities is
  54.  * complicated by the fact that very long fixed point representations look
  55.  * much worse than the same sized floating point representation.  Further,
  56.  * a fixed point number with a large negative exponent will actually gain
  57.  * in precision when written as floating point.  Thus we use certain fuzz
  58.  * factors to get 'digfix' from 'digmax', however it will always be true
  59.  * that digfix<=digmax.
  60.  *
  61.  * Finally, if 'digmax' is set, 'prec' is reduced in size if necessary so
  62.  * that the labels fit the requested field length.
  63. \*----------------------------------------------------------------------*/
  64.  
  65. void
  66. pldtik(PLFLT vmin, PLFLT vmax, PLFLT *tick, PLINT *nsubt,
  67.        PLINT *mode, PLINT *prec, PLINT digmax, PLINT *scale)
  68. {
  69.     PLFLT t0, t1, t2, vmod;
  70.     PLINT msd, np, ns, digmin, digfix, autoscale = 0;
  71.  
  72.     *mode = 0;
  73.     *scale = 0;
  74.     if (*tick == 0.0)
  75.     autoscale = 1;
  76.     if (digmax == 0)
  77.     digmax = DIGMAX_DEF;
  78.  
  79. /* Magnitute of min/max to get number of significant digits */
  80.  
  81.     vmod = MAX(ABS(vmin), ABS(vmax));
  82.     t0 = (PLFLT) log10(vmod);
  83.     msd = (PLINT) floor(t0);
  84.  
  85. /* Autoselect the mode flag */
  86. /* 'digmin' is the minimum number of places taken up by the label */
  87.  
  88.     if (msd >= 0) {
  89.     digmin = msd + 1;
  90.     digfix = MAX_FIXDIG_POS;
  91.     if (digmax > 0)
  92.         digfix = MIN(digmax, MAX_FIXDIG_POS);
  93.     }
  94.     else {
  95.     digmin = -msd + 2;
  96.     digfix = MAX_FIXDIG_NEG;
  97.     if (digmax > 0)
  98.         digfix = MIN(digmax, MAX_FIXDIG_NEG);
  99.     }
  100.  
  101.     if (digmin > digfix) {
  102.     *mode = 1;
  103.     *scale = msd;
  104.     }
  105.  
  106. /* Magnitude of min/max difference to get tick spacing */
  107.  
  108.     t1 = (PLFLT) log10(ABS(vmax - vmin));
  109.     np = (PLINT) floor(t1);
  110.     t1 = t1 - np;
  111.  
  112. /* Get tick spacing. */
  113.  
  114.     if (t1 > 0.7781512503) {
  115.     t2 = 2.0;
  116.     ns = 4;
  117.     }
  118.     else if (t1 > 0.4771212549) {
  119.     t2 = 1.0;
  120.     ns = 5;
  121.     }
  122.     else if (t1 > 0.1760912591) {
  123.     t2 = 5.0;
  124.     ns = 5;
  125.     np = np - 1;
  126.     }
  127.     else {
  128.     t2 = 2.0;
  129.     ns = 4;
  130.     np = np - 1;
  131.     }
  132.  
  133. /* Now compute tick spacing */
  134.  
  135.     if (autoscale) {
  136.     *tick = t2 * pow(10.0, (double) np);
  137.     if (vmin > vmax)
  138.         *tick = -*tick;
  139.     }
  140.     else {
  141.     t1 = log10(ABS(*tick));
  142.     np = (PLINT) floor(t1);
  143.     }
  144.     if (*nsubt == 0)
  145.     *nsubt = ns;
  146.  
  147. /* Establish precision.  */
  148.  
  149.     if (*mode != 0)
  150.     *prec = msd - np;
  151.     else
  152.     *prec = MAX(-np, 0);
  153.  
  154. /* One last hack required here: if exponent < 0, i.e. number has leading
  155.    '0.', it is better to change to floating point form if the number of
  156.     digits is insufficient to represent the tick spacing. */
  157.  
  158.     if (autoscale) {
  159.     if (*mode == 0 && digmax > 0) {
  160.         if (t0 < 0.0) {
  161.         if (digmax - 2 - *prec < 0) {
  162.             *mode = 1;
  163.             *scale = msd;
  164.         }
  165.         }
  166.         else
  167.         *prec = MAX(MIN(*prec, digmax - msd - 1), 0);
  168.     }
  169.     if (*mode != 0) {
  170.         *prec = msd - np;
  171.         *prec = MAX(MIN(*prec, MAX(digmax-1, MIN_FLTDIG)), 0);
  172.     }
  173.     }
  174. }
  175.